﻿
using dbcTools;
using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace DBCTools.Tools
{
	class csvReader : dbcStruct
	{
		public csvReader (string file, MainWindow mw )
		{
			mainWindow = mw;
			fileName = file.Substring(file.LastIndexOf("\\") + 1);
			dbcStort2 = new Dictionary<uint, byte[]>();
			csvStore = new List<string[]>();
			hasPrimarykey = false;
			readCSVFile(file);
			FillDBCData();
			writeDbc(fileName + ".dbc", mw);
		}

		private void readCSVFile(string file)
		{
			if (!File.Exists(file))
				throw new Exception(fileName + "文件不存在.");

			
			var fileInfo = new FileInfo(file);
			var totalSize = fileInfo.Length;

			var fs = fileInfo.OpenRead();
			var sr = new StreamReader(fs);

			FileStruct = sr.ReadLine().Replace(",", "");

			string csvDataLine = "";
			mainWindow.SetProBarMsg("载入[" + fileName + "]中....");

			while (true)
			{
				string fileDataLine = sr.ReadLine();

				if (fileDataLine == null)
					break;
				
				//如果csvDataLine空的 说明是新的一行数据 否则说明数据包含换行符需要和下一行的数据合并
				if (csvDataLine == "")
					csvDataLine = fileDataLine;
				else
					csvDataLine += "\r\n" + fileDataLine;

				//如果包含偶数个引号，说明该行数据中出现回车符或包含逗号
				if (!IfOddQuota(csvDataLine))
				{
					AddNewDataLine(csvDataLine);

					csvDataLine = "";
				};

				mainWindow.SetProBar((uint)(fs.Position * 100 / totalSize) + 1);
			}
			sr.Close();
			fs.Close();
		}

		private void FillDBCData()
		{
			mainWindow.SetProBarMsg("分析[" + fileName + "]数据中....");
			dbcStore1 = new Dictionary<uint, byte[]>();
			RowCount = (uint)csvStore.Count;
			ColumnCount = (uint)FileStruct.Length;
			RowSize = 0;
			foreach (var i in FileStruct)
			{
				if (i == 'u' || i == 'i' || i == 'f' || i == 's' || i == 'x')
					RowSize += 4;
				else if (i == 'b')
					RowSize += 1;
			}
			
			List<byte> stringBlock = new List<byte>();
			//第一个必须为0 否则0索引到的空字符串会变成有效
			stringBlock.Add(new byte());
			uint jdt = 0;
			foreach (var val in csvStore)
			{
				List<byte> row = new List<byte>();
				for (int i = 0; i < val.Length; i++)
				{
					switch (FileStruct[i])
					{
						case 'u':
							{
								row.AddRange(BitConverter.GetBytes(uint.Parse(val[i])));
								continue;
							}
						case 'i':
							{
								row.AddRange(BitConverter.GetBytes(int.Parse(val[i])));
								continue;
							}
						case 'x':
							{
								string hex = val[i].Replace("0x", "");
								int intValue = int.Parse(hex,System.Globalization.NumberStyles.HexNumber);
								row.AddRange(BitConverter.GetBytes(intValue));
								continue;
							}
						case 'f':
							{
								row.AddRange(BitConverter.GetBytes(float.Parse(val[i])));
								continue;
							}
						case 'b':
							{
								row.Add(byte.Parse(val[i]));
								continue;
							}
						case 's':
							{
								if (val[i]!= "")
								{ 
									row.AddRange(BitConverter.GetBytes(stringBlock.Count));

									stringBlock.AddRange(Encoding.UTF8.GetBytes(val[i]));
								
									stringBlock.Add(new byte());
								}
								else
								{
									row.AddRange(BitConverter.GetBytes(0));
								}
								continue;
							}
					}
				}
				dbcStort2.Add(jdt, row.ToArray());
				mainWindow.SetProBar(((jdt++) * 100) / ((uint)csvStore.Count) + 1);
			}
			StringBlockSize = (uint)stringBlock.Count;
			StringBlock = stringBlock.ToArray();
			mainWindow.SetProBar(0);
			mainWindow.SetProBarMsg("");
		}

		private void AddNewDataLine(string csvDataLine)
		{
			string[] val = csvDataLine.Split(',');
			if (val.Length == FileStruct.Length)
			{
				//如果根据<,>分割字符串后和结构列数相符,则认为该条数据不含需特殊处理的内容.
				string value = "";
				for (int i = 0; i < val.Length; i++)
				{
					foreach (var ii in val[i])
					{
						if (ii != '"')
							value += ii.ToString();

					}
					val[i] = value;
					value = "";
				}
				csvStore.Add(val);
			}
			else
			{
				bool hasQuotes = false;
				val = new string[FileStruct.Length];
				string value = "";
				int index = 0;

				for (int i = 0; i < csvDataLine.Length; i++)
				{
					if (!hasQuotes)
					{
						if (csvDataLine[i] == '\"')
						{
							hasQuotes = true;
							continue;
						}

						if (csvDataLine[i] == ',')
						{
							val[index++] = value;
							value = "";
							continue;
						}
					}
					else
					{
						if (csvDataLine[i] == '\"' && csvDataLine[i + 1]== ',')
						{
							hasQuotes = false;
							continue;
						}
					}
					value += csvDataLine[i];
				}

				val[index++] = value;
				csvStore.Add(val);
			}
		}


		/// <summary>
		/// 判断字符串是否包含奇数个引号
		/// </summary>
		/// <param name="dataLine">数据行</param>
		/// <returns>为奇数时，返回为真；否则返回为假</returns>
		private bool IfOddQuota(string dataLine)
		{
			int quotaCount;
			bool oddQuota;

			quotaCount = 0;

			for (int i = 0; i < dataLine.Length; i++)
				if (dataLine[i] == '\"')
					quotaCount++;

			oddQuota = false;
			if (quotaCount % 2 == 1)
				oddQuota = true;
			
			return oddQuota;
		}

		private List<string[]> csvStore;

		public string FileStruct;
		private MainWindow mainWindow;
		private string fileName;
	}
}
